//#define __DEBUG__
// by Xeno
#define THIS_FILE "fn_spectating.sqf"
#include "xr_macros.sqf"

__TRACE("start");
private ["_withresp", "_disp", "_pllist", "_plnamelist", "_u", "_uc", "_add", "_idx", "_forEachIndex", "_campos", "_updatelb", "_timer", "_h", "_fangle", "_fangleY", "_sdistance", "_setidx", "_bb", "_foo", "_hstr", "_vpmtw", "_cxpos", "_cypos", "_czpos", "_gjp", "_lsdist", "_l", "_d", "_z", "_co","_l", "_player_has_no_lifes", "_nposvis"];
GVARXR(MouseCoord) = [0.5,0.5];
GVARXR(MouseScroll) = 0;
GVARXR(MouseButtons) = [false,false];
GVARXR(mouseDeltaPos) = [0,0];
GVARXR(mouseLastX) = 0.5;
GVARXR(mouseLastY) = 0.5;
//TYRGHEN
GVARXR(maxDistance) = GVARXR(revive_cam_max_dist);
GVARXR(sdistance) = 1;
GVARXR(szoom) = 0.976;
GVARXR(fangle) = 0;
GVARXR(fangleY) = 15;
GVARXR(mousecheckon) = false;
disableSerialization;
if (!isNil QGVARXR(stopspect) && {!GVARXR(stopspect)}) then  {
	waitUntil {GVARXR(stopspect)};
	sleep 0.2;
};
GVARXR(stopspect) = false;
enableRadio false;
PARAMS_1(_withresp);
__TRACE_1("","_withresp");
if (_withresp) then {
	__TRACE("_withresp, cutText");
	173 cutText [localize "STR_DOM_MISSIONSTRING_921","PLAIN", 0];
	sleep 3;
};
__TRACE("black in 3");
172 cutText ["","BLACK IN", 3];
_player_has_no_lifes = __pGetVar(GVARXR(lives)) == -1;
__TRACE_1("","_player_has_no_lifes");
GVARXR(camnvgon) = false;
createDialog QGVARXR(SpectDlg);
_disp = __uiGetVar(GVARXR(SpectDlg));
#define __dspctrl(ctrlid) (_disp displayCtrl ctrlid)
__dspctrl(1000) ctrlShow false;
__dspctrl(1001) ctrlShow false;
#define __spectdlg1006e (__uiGetVar(GVARXR(SpectDlg)) displayCtrl 1006)
if (!_withresp) then {
	__dspctrl(1020) ctrlShow false;
	__dspctrl(1021) ctrlShow false;
	__dspctrl(1005) ctrlShow false;
	__dspctrl(1006) ctrlShow false;
} else {
	if (GVARXR(respawn_available)) then {
		__spectdlg1006e ctrlSetText (localize "STR_DOM_MISSIONSTRING_922");
		__spectdlg1006e ctrlSetTextColor [1,1,0,1];
		__spectdlg1006e ctrlCommit 0;
	};
};

_pllist = if (!_player_has_no_lifes) then {[str player]} else {[]};
__TRACE_1("","_pllist");
_plnamelist = if (!_player_has_no_lifes) then {[GVARXR(name_player)]} else {[]};
__TRACE_1("","_plnamelist");
_helperls = [];
if (!_player_has_no_lifes) then {
	{
		_u = __getMNsVar2(_x);
		if (!isNil "_u" && {!isNull _u} && {alive _u} && {side (group _u) == GVARXR(side_pl)} && {_u != player}) then {
			_uc = __GV(_u,GVARXR(pluncon));
			if (!isNil "_uc" && {!_uc}) then {
				_add = true;
				_distup = -1;
				if (_withresp) then {
					_vu = vehicle _u;
					_upos = if (!surfaceIsWater (getPosASL _vu)) then {
						ASLToATL (visiblePositionASL _vu)
					} else {
						visiblePosition _vu
					};
					_distup = _upos distance player;
					if (_distup > GVARXR(near_player_dist)) then {_add = false};
				};
				if (_add) then {
					_helperls set [count _helperls, [_distup, str _u, name _u]];
				};
			};
		};
	} forEach GVARXR(player_entities);
} else {
	_sfm = markerPos QGVARXR(playerparkmarker);
	_sfm set [2,0];
	{
		_u = __getMNsVar2(_x);
		if (!isNil "_u" && {!isNull _u} && {alive _u} && {side (group _u) == GVARXR(side_pl)} && {_u != player}) then {
			_distup = _u distance _sfm;
			if (_distup > 100) then {
				_helperls set [count _helperls, [_distup, str _u, name _u]];
			};
		};
	} forEach GVARXR(player_entities);
};
if (count _helperls > 0) then {
	_helperls = [_helperls, 0] call d_fnc_SortAR;
	{
		_pllist set [count _pllist, _x select 1];
		_plnamelist set [count _plnamelist, _x select 2];
	} forEach _helperls;
};
_helperls = nil;
_helperls = [];

lbClear (__uiGetVar(GVARXR(SpectDlg)) displayCtrl 1000);
{
	_idx = lbAdd [1000, _plnamelist select _forEachIndex];
	lbSetData [1000, _idx, _x];
} forEach _pllist;
showcinemaborder false;
if (!_player_has_no_lifes) then {
	_vkegs = vehicle player;
	_nposvis = if (!surfaceIsWater (getPosASL _vkegs)) then {
		ASLToATL (visiblePositionASL _vkegs)
	} else {
		visiblePosition _vkegs
	};
	_campos = [(_nposvis select 0) - 1 + random 2, (_nposvis select 1) - 1 + random 2, 2];
	GVARXR(spectcam) = "camera" camCreate _campos;
	GVARXR(spectcamtarget) = player;
	GVARXR(spectcamtargetstr) = str player;
	GVARXR(spectcam) cameraEffect ["INTERNAL", "Back"];
	GVARXR(spectcamrelpos) = [-2, -2, 2];
	GVARXR(spectcam) camCommit 0;
	__dspctrl(1010) ctrlSetText GVARXR(name_player);
} else {
	_sfm = markerPos QGVARXR(playerparkmarker);
	_visobj = objNull;
	{
		_u = __getMNsVar2(_x);
		if (!isNil "_u" && {!isNull _u} && {alive _u} && {side (group _u) == GVARXR(side_pl)} && {_u != player} && {_u distance _sfm > 100}) exitWith {
			_visobj = _u;
		};
	} forEach GVARXR(player_entities);
	if (isNull _visobj) then {_visobj = player};
	_vkegs = vehicle _visobj;
	_nposvis = if (!surfaceIsWater (getPosASL _vkegs)) then {
		ASLToATL (visiblePositionASL _vkegs)
	} else {
		visiblePosition _vkegs
	};
	_campos = [(_nposvis select 0) - 1 + random 2, (_nposvis select 1) - 1 + random 2, 2];
	GVARXR(spectcam) = "camera" camCreate _campos;
	GVARXR(spectcamtarget) = _visobj;
	GVARXR(spectcamtargetstr) = str _visobj;
	GVARXR(spectcam) cameraEffect ["INTERNAL", "Back"];
	GVARXR(spectcamrelpos) = [-2, -2, 2];
	GVARXR(spectcam) camCommit 0;
	__dspctrl(1010) ctrlSetText (name _visobj);
};
_updatelb = true;
_timer = time + 10;
_h = 2;
__TRACE("main loop starts");
while {!GVARXR(stopspect)} do {
	_fangle = GVARXR(fangle);
	_fangleY = GVARXR(fangleY);
	GVARXR(mouseDeltaPos) set [0, GVARXR(mouseLastX) - (GVARXR(MouseCoord) select 0)];
	GVARXR(mouseDeltaPos) set [1, GVARXR(mouseLastY) - (GVARXR(MouseCoord) select 1)];
	GVARXR(mouseLastX) = GVARXR(MouseCoord) select 0;
	GVARXR(mouseLastY) = GVARXR(MouseCoord) select 1;
	if (GVARXR(MouseScroll) != 0) then {
		GVARXR(sdistance) = GVARXR(sdistance) - (GVARXR(MouseScroll) * 0.11);
		GVARXR(MouseScroll) = GVARXR(MouseScroll) * 0.75;
		switch (true) do {
			case (GVARXR(sdistance) > GVARXR(maxDistance)): {GVARXR(sdistance) = GVARXR(maxDistance)};
			case (GVARXR(sdistance) < -GVARXR(maxDistance)): {GVARXR(sdistance) = -GVARXR(maxDistance)};
		};
		if (GVARXR(sdistance) < -0.6) then {GVARXR(sdistance) = -0.6};
	};
	_sdistance = GVARXR(sdistance);

	if (time > _timer) then {
		if (!_player_has_no_lifes) then {
			_pllist = if (_withresp) then {[str player]} else {[]};
			_plnamelist = if (_withresp) then {[GVARXR(name_player)]} else {[]};
		} else {
			_pllist = [];
			_plnamelist = [];
		};
		_helperls = [];
		if (!_player_has_no_lifes) then {
			{
				_u = __getMNsVar2(_x);
				if (!isNil "_u" && {!isNull _u} && {alive _u} && {side (group _u) == GVARXR(side_pl)} && {_u != player}) then {
					_uc = __GV(_u,GVARXR(pluncon));
					if (!isNil "_uc" && {!_uc}) then {
						_add = true;
						_distup = -1;
						if (_withresp) then {
							_vu = vehicle _u;
							_upos = if (!surfaceIsWater (getPosASL _vu)) then {
								ASLToATL (visiblePositionASL _vu)
							} else {
								visiblePosition _vu
							};
							_distup = _upos distance player;
							if (_distup > GVARXR(near_player_dist)) then {
								_add = false;
							};
						};
						if (_add) then {
							_helperls set [count _helperls, [_distup, str _u, name _u]];
						};
					};
				};
			} forEach GVARXR(player_entities);
		} else {
			_sfm = markerPos QGVARXR(playerparkmarker);
			_sfm set [2,0];
			{
				_u = __getMNsVar2(_x);
				if (!isNil "_u" && {!isNull _u} && {alive _u} && {side (group _u) == GVARXR(side_pl)} && {_u != player}) then {
					_distup = _u distance _sfm;
					if (_distup > 100) then {
						_helperls set [count _helperls, [_distup, str _u, name _u]];
					};
				};
			} forEach GVARXR(player_entities);
		};
		if (count _helperls > 0) then {
			_helperls = [_helperls, 0] call d_fnc_SortAR;
			{
				_pllist set [count _pllist, _x select 1];
				_plnamelist set [count _plnamelist, _x select 2];
			} forEach _helperls;
		};
		_updatelb = true;
		_timer = time + 10;
		_helperls = nil;
	};
	if (_updatelb && {!isNil {__uiGetVar(GVARXR(SpectDlg))}} && {ctrlShown (__uiGetVar(GVARXR(SpectDlg)) displayCtrl 1000)}) then {
		__TRACE_1("","_updatelb");
		_updatelb = false;
		lbClear (__uiGetVar(GVARXR(SpectDlg)) displayCtrl 1000);
		_setidx = -1;
		{
			_idx = lbAdd [1000, _plnamelist select _forEachIndex];
			lbSetData [1000, _idx, _x];
			if (GVARXR(spectcamtargetstr) == _x) then {_setidx = _forEachIndex};
		} forEach _pllist;
		if (_setidx != -1) then {lbSetCurSel [1000, _setidx]};
	};
	// user pressed ESC
	//__TRACE("before spectating ctrl check");
	_spectdisp = __uiGetVar(GVARXR(SpectDlg));
	if ((isNil "_spectdisp" || {!ctrlShown (_spectdisp displayCtrl 1002)}) && {!GVARXR(stopspect)} && {__pGetVar(GVARXR(pluncon))}) then {
		__TRACE("ctrl not shown anymore, black out");
		172 cutText ["","BLACK OUT", 1];
		sleep 3;
		if (!alive player) then { // should not happen
			__TRACE("player not alive");
			waitUntil {alive player};
			sleep 0.1;
		};
		__TRACE("creating new dialog");
		createDialog QGVARXR(SpectDlg);
		_disp = __uiGetVar(GVARXR(SpectDlg));
		#define __dspctrl(ctrlid) (_disp displayCtrl ctrlid)
		__dspctrl(1000) ctrlShow false;
		__dspctrl(1001) ctrlShow false;
		if (GVARXR(respawn_available)) then {
			__spectdlg1006e ctrlSetText (localize "STR_DOM_MISSIONSTRING_922");
			__spectdlg1006e ctrlSetTextColor [1,1,0,1];
			__spectdlg1006e ctrlCommit 0;
		};
		if (!_player_has_no_lifes) then {
			GVARXR(spectcamtarget) = player;
			GVARXR(spectcamtargetstr) = str player;
			GVARXR(spectcam) cameraEffect ["INTERNAL", "Back"];
			GVARXR(spectcamrelpos) = [-2, -2, 2];
			GVARXR(spectcam) camCommit 0;
			__dspctrl(1010) ctrlSetText GVARXR(name_player);
		} else {
			_sfm = markerPos QGVARXR(playerparkmarker);
			_visobj = objNull;
			{
				// TYRGHEN - Missing isNil test
				if (!isNil "_u" && {!isNull _u} && {alive _u} && {side (group _u) == GVARXR(side_pl)} && {_u != player} && {_u distance _sfm > 100}) exitWith {
						_visobj = _u;
				};
			} forEach GVARXR(player_entities);
			if (isNull _visobj) then {_visobj = player};
			_vkegs = vehicle _visobj;
			_nposvis = if (!surfaceIsWater (getPosASL _vkegs)) then {
				ASLToATL (visiblePositionASL _vkegs)
			} else {
				visiblePosition _vkegs
			};
			_campos = [(_nposvis select 0) - 1 + random 2, (_nposvis select 1) - 1 + random 2, 2];
			GVARXR(spectcam) = "camera" camCreate _campos;
			GVARXR(spectcamtarget) = _visobj;
			GVARXR(spectcamtargetstr) = str _visobj;
			GVARXR(spectcam) cameraEffect ["INTERNAL", "Back"];
			GVARXR(spectcamrelpos) = [-2, -2, 2];
			GVARXR(spectcam) camCommit 0;
			__dspctrl(1010) ctrlSetText (name _visobj);
		};
		_timer = -1;
		__TRACE("ctrl not shown anymore, black in");
		172 cutText ["","BLACK IN", 1];
	};
	if (isNull GVARXR(spectcamtarget)) then { // player disconnect !?!
		_vkegs = vehicle player;
		_nposvis = if (!surfaceIsWater (getPosASL _vkegs)) then {
			ASLToATL (visiblePositionASL _vkegs)
		} else {
			visiblePosition _vkegs
		};
		_campos = [(_nposvis select 0) - 1 + random 2, (_nposvis select 1) - 1 + random 2, 2];
		GVARXR(spectcamtarget) = player;
		GVARXR(spectcamtargetstr) = str player;
		GVARXR(spectcam) cameraEffect ["INTERNAL", "Back"];
		GVARXR(spectcamrelpos) = [-2, -2, 2];
		GVARXR(spectcam) camCommit 0;
		__dspctrl(1010) ctrlSetText GVARXR(name_player);
	};
	
	_bb = boundingboxreal vehicle GVARXR(spectcamtarget);
	_foo = ((_bb select 1) select 2) - ((_bb select 0) select 2);
	_l = ((_bb select 1) select 1) - ((_bb select 0) select 1);
	_hstr = 0.15;
	_h = (_foo * _hstr) + (_h * (1 - _hstr));
	
	_vkegs = vehicle GVARXR(spectcamtarget);
	_vpmtw = if (!surfaceIsWater (getPosASL _vkegs)) then {
		ASLToATL (visiblePositionASL _vkegs)
	} else {
		visiblePosition _vkegs
	};
	_cxpos = _vpmtw select 0;
	_cypos = _vpmtw select 1;
	_czpos = _vpmtw select 2;

	_gjp = [_cxpos, _cypos, _czpos + (_h * 0.6)];
	GVARXR(spectcam) camSetTarget _gjp;
	GVARXR(spectcam) camSetFov GVARXR(szoom);
	
	_lsdist = _l * (0.3 max _sdistance);
	_d = -_lsdist;
	_z = sin _fangleY * _lsdist;
	_co = cos _fangleY;
	GVARXR(spectcam) camSetRelPos [(sin _fangle * _d) * _co, (cos _fangle * _d) * _co, _z];
	GVARXR(spectcam) camCommit 0;
	sleep 0.0034;
	//if (!__pGetVar(GVARXR(pluncon)) && {!_player_has_no_lifes}) exitWith {GVARXR(stopspect) = true};
};
closeDialog 0;
player switchCamera "INTERNAL";
GVARXR(spectcam) CameraEffect ["Terminate", "Back"];
camDestroy GVARXR(spectcam);
enableRadio true;
__TRACE("end");